﻿// SyntheticDataGenerator.ParameterSets.TaxonomyParameters
//
// (c) 2011 Arthur Pitman
//
// Part of Market-Basket Synthetic Data Generator
// A C# adaptation of the IBM Quest Market-Basket Synthetic Data Generator
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// (Version 2) as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// License (Version 2) along with this program; if not, write to 
// the Free Software Foundation, Inc., 
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// or see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace SyntheticDataGenerator.ParameterSets
{
    /// <summary>
    /// Taxonomy parameters
    /// </summary>
    public class TaxonomyParameters : TransactionParameters
    {        
        /// <summary>
        /// Number of roots
        /// </summary>
        public int RootCount { get; set; }

        /// <summary>
        /// Average fanout at each interior node
        /// </summary>
        public double Fanout { get; set; }

        /// <summary>
        /// Average number of levels
        /// </summary>
        public double AverageLevelCount { get; set; }

        /// <summary>
        /// Depth ratio: affects ratio of itemsets chosen from higher levels
        /// </summary>
        public double DepthRatio { get; set; }	 

        /// <summary>
        /// Initializes a new <see cref="TaxonomyParameters"/> instance with default values
        /// </summary>
        public TaxonomyParameters()
        {
            RootCount = 250;
            Fanout = 5;
            AverageLevelCount = 0;
            DepthRatio = 1;
        }
        
        /// <summary>
        /// Calculates <c>RootCount</c> given <c>AverageLevelCount</c> and vice versa, or default values
        /// nroots = 250, fanout = 5
        /// </summary>
        public void CalculateValues()
        {

            if ((Fanout == 0) && (RootCount == 0))
            {
                RootCount = 250;
                Fanout = 5;
            }
            else if ((Fanout == 0) && (RootCount != 0))
            {
                if (AverageLevelCount == 0)
                {
                    Fanout = 5;
                }
                else
                {
                    double temp = ((double)ItemCount) / RootCount - 1;
                    temp = Math.Log(temp) / (AverageLevelCount - 1);
                    Fanout = Math.Exp(temp);
                }
            }
            else if ((RootCount == 0) && (Fanout != 0))
            {
                if (AverageLevelCount == 0)
                {
                    RootCount = 250;
                }
                else
                {
                    // check this type cast!
                    RootCount = (int)(ItemCount / (1 + Math.Pow(Fanout, AverageLevelCount - 1)));
                    if (RootCount < 1)
                        RootCount = 1;
                }
            }
        }

        /// <summary>
        /// Writes parameters to a <see cref="TextWriter"/>
        /// </summary>
        /// <param name="writer"></param>
        public override void Write(TextWriter writer)
        {
            base.Write(writer);
            writer.WriteLine("RootCount={0}, LevelCount={1}, FanOut={2}, DepthRatio = {3}", RootCount, AverageLevelCount, Fanout, DepthRatio);
        }
    }
}
